今天我們來將前兩天提到的 JWT 實作出來,並以 Day15 的 RESTful API 實作方式互相結合,以 API 的方式實作 JWT 的認證。
tymon/jwt-auth
引用進來(建議版本在 1.0 以上)composer require tymon/jwt-auth
config/app.php
內新增 Service Provider'providers' => [
...
Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
]
config/jwt.php
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
php artisan jwt:secret
namespace App;
...
use Illuminate\Foundation\Auth\User as Authenticatable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
...
public function getJWTIdentifier()
{
return $this->getKey();
}
public function getJWTCustomClaims()
{
return[];
}
...
}
config/auth.php
內更改認證方式,將 guard 的認證方式改為 api,api 的 driver 改為 jwt,程式碼如下'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
...
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
routes/api.php
Route::group([
'prefix' => 'auth'
], function ($router) {
Route::post('login', [AuthController::class,'login']);
Route::post('logout', [AuthController::class,'logout']);
Route::post('refresh', [AuthController::class,'refresh']);
Route::post('me', [AuthController::class,'me']);
});
php artisan make:controller AuthController
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
class AuthController extends Controller
{
/**
* Create a new AuthController instance
*
* @return void
*/
public function __construct()
{
$this->middleware('auth:api', ['except' => ['login']]);
}
/**
* Get a JWT via given credentials.
*
* @return \Illuminate\Http\JsonResponse
*/
public function login()
{
$credentials = request(['email', 'password']);
if (!$token = Auth::guard()->attempt($credentials)) {
return response()->json(['error' => 'Unauthorize'], 401);
}
return $this->respondWithToken($token);
}
/**
* Get a authenticated User.
*
* @return \Illuminate\Http\JsonResponse
*/
public function me()
{
return response()->json(Auth::guard()->user());
}
/**
* Log the user out(Invalidate the Token).
*
* @return \Illuminate\Http\JsonResponse
*/
public function logout()
{
Auth::guard()->logout();
return response()->json(['message'=>'Successfully logged out']);
}
/**
* Refresh a Token.
*
* @return \Illuminate\Http\JsonResponse
*/
public function refresh()
{
return $this->respondWithToken(Auth::guard()->refresh());
}
protected function respondWithToken($token)
{
return response()->json([
'access_token'=>$token,
'token_type'=>'bearer',
'expires_in'=>Auth::guard()->factory()->getTTL()*60
]);
}
}
此時就可以使用 Postman 來測試 API,以下是先前新增的測試帳號,GET localhost:8000/api/users
POST localhost/api/auth/login 並在 body 加入設定好的 email、password,在 Headers 中加入 Content-Type: application/json,即可拿到一串 access token,依照昨天所說的 JWT 設計規範,我們這邊的實作是直接使用 refresh token 作為 access token
以上就是 JWT 的實作囉,不過實際應用狀況會根據各種系統的設計以及業務邏輯有不同微調,依我之前的經驗,通常系統剛開始設計時,登入流程就會有很多不同的做法,考驗前後端的相互配合。